<template>
  <div :class="!readonly && 'cursor-pointer'">
      <PortalToFollowElem
        v-model:open="open"
        :placement="isAddBtnTrigger ? 'bottom-end' : 'bottom-start'"
      >
        <template #trigger>
          <div @click="(e) => {
            if (readonly) {
              e.stopPropagation()
              return
            }
            !isConstant ? open = (!open) :controlFocus =Date.now()
          }" class='group/picker-trigger-wrap relative !flex'>
                  <div v-if="isAddBtnTrigger">
                    <Button ><PlusOutlined/> </Button>
                  </div>
                  <div 
                  :class="cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'group/wrap relative flex h-8 w-full items-center', !isSupportConstantValue && 'rounded-lg bg-components-input-bg-normal p-1', isInTable && 'border-none bg-transparent', readonly && 'bg-components-input-bg-disabled')">
                    <div v-if="isSupportConstantValue" @click="(e) => {
                      e.stopPropagation()
                      open = false
                      controlFocus = Date.now()
                    }"  class='mr-1 flex h-full items-center space-x-1'>
                      <TypeSelector
                        noLeft
                        popupClassName='top-8'
                        :readonly="readonly"
                        :value="varKindType"
                        :options="varKindTypes"
                        :onChange="handleVarKindTypeChange"
                        showChecked
                      >
                      <template #trigger>
                        <div class='radius-md flex h-8 items-center bg-components-input-bg-normal px-2'>
                            <div class='system-sm-regular mr-1 text-components-input-text-filled'>{{varKindTypes.find(item => item.value === varKindType)?.label}}</div>
                            <RiArrowDownSLine class='h-4 w-4 text-text-quaternary' />
                          </div>
                      </template>
                    </TypeSelector>
                    </div>
                    <div v-if="!isSupportConstantValue && !hasValue" class='ml-1.5 mr-1'>
                      <Variable02 :class="`h-4 w-4 ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'}`" />
                    </div>
                      <ConstantField v-if="isConstant"
                        :value="value"
                        @change="onChange"
                        :schema="schema"
                        :readonly="readonly"
                      />
                      <VarPickerWrap v-if="!isConstant"
                        @click="() => {
                          if (readonly)
                            return
                          !isConstant ? open = (!open) : controlFocus = Date.now()
                        }"
                        class='h-full grow'
                      >
                        <div 
                        :class="cn('h-full', isSupportConstantValue && 'flex items-center rounded-lg bg-gray-100 py-1 pl-1')">
                          <Tooltip :content="!isValidVar && hasValue && '无效的变量'">
                            <div :class="cn('h-full items-center rounded-[5px] px-1.5', hasValue ? 'inline-flex bg-white' : 'flex')">
                                  <template v-if="hasValue">
                                    <div v-if="isShowNodeName && !isEnv && !isChatVar" class='flex items-center'>
                                      <div class='h-3 px-[1px]'>
                                        <VarBlockIcon v-if="outputVarNode?.type"
                                          class='!text-gray-900'
                                          type="outputVarNode.type"
                                        />
                                      </div>
                                      <div class='mx-0.5 truncate text-xs font-medium text-gray-700' :title="outputVarNode?.title"
                                        :style="{maxWidth: maxNodeNameWidth}",
                                      >{{outputVarNode?.title}}</div>
                                    </div>
                                    <div class='flex items-center text-primary-600'>
                                      <div :class="cn('ml-0.5 truncate text-xs font-medium', isEnv && '!text-text-secondary', isChatVar && 'text-util-colors-teal-teal-700', isException && 'text-text-warning')"
                                        :title="varName" :style="{
                                        maxWidth: maxVarNameWidth,
                                      }">{{varName}}</div>
                                    </div>
                                    <div class='system-xs-regular ml-0.5 truncate text-center capitalize text-text-tertiary' :title="type" :style="{
                                      maxWidth: maxTypeWidth,
                                    }">{{type}}</div>
                                    <RiErrorWarningFill v-if="!isValidVar" class='ml-0.5 h-3 w-3 text-[#D92D20]' />
                                  </template>
                                  <div v-if="!hasValue" :class="`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} system-sm-regular text-ellipsis`">
                                  {{placeholder ?? '设置变量值'}}</div>}
                            </div>
                          </Tooltip>
                        </div>
                      </VarPickerWrap>
                  <div v-if="(hasValue && !readonly && !isInTable)"
                    class='group invisible absolute right-1 top-[50%] h-5 translate-y-[-50%] cursor-pointer rounded-md p-1 hover:bg-black/5 group-hover/wrap:visible'
                    @click="handleClearVar"
                  >
                    <RiCloseLine class='h-3.5 w-3.5 text-gray-500 group-hover:text-gray-800' />
                  </div>
                    <Badge v-if="!hasValue && valueTypePlaceHolder"
                      class=' absolute right-1 top-[50%] translate-y-[-50%] capitalize'
                      :text="valueTypePlaceHolder"
                      :uppercase="false"
                    />
                </div>
                <Button  v-if="!readonly && isInTable "
                  class='absolute right-1 top-0.5 hidden group-hover/picker-trigger-wrap:block'
                  @click="() => onRemove?.()"
                ><PlusOutlined /></Button>

                <Badge v-if="!hasValue && typePlaceHolder"
                  class='absolute right-2 top-1.5'
                  :text="typePlaceHolder"
                  :uppercase="false"
                />
          </div>
        </template>
          <div :style="{
            zIndex: zIndex || 100,
          }" class='mt-1'>
              <VarReferencePopup v-if="!isConstant"
                :vars="outputVars"
                :popupFor="popupFor"
                @change="handleVarReferenceChange"
                :itemWidth="isAddBtnTrigger ? 260 : (minWidth || triggerWidth)"
                :isSupportFileVar={isSupportFileVar}
              />
          </div>
      </PortalToFollowElem>
    </div >
</template>
<script setup lang="ts" name="VarReferencePicker">
import {computed, ref, watch} from 'vue';
import {
  RiArrowDownSLine,
  RiCloseLine,
  RiErrorWarningFill,
} from '@remixicon/vue'
import useAvailableVarList from '../../hooks/use-available-var-list'
import VarReferencePopup from './var-reference-popup.vue'
import { getNodeInfoById, isConversationVar, isENV, isSystemVar } from './utils'
import ConstantField from './constant-field.vue'
import cn from '@/utils/classnames'
import type { Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { BlockEnum } from '@/app/components/workflow/types'
import PortalToFollowElem from '@/components/portal-to-follow-elem/index.vue'
import {
  useIsChatMode,
  useWorkflowVariables,
} from '@/app/components/workflow/hooks'
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
import Badge from '@/components/base/badge.vue'
import { Tooltip } from 'ant-design-vue'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import { Button } from 'ant-design-vue'
import { PlusOutlined } from '@ant-design/icons-vue'
import { useVueFlow } from '@vue-flow/core'

const TRIGGER_DEFAULT_WIDTH = 227

type Props = {
  nodeId: string
  isShowNodeName?: boolean
  readonly: boolean
  value: ValueSelector | string
  onChange: (value: ValueSelector | string, varKindType: VarKindType, varInfo?: Var) => void
  onOpen?: () => void
  isSupportConstantValue?: boolean
  defaultVarKindType?: VarKindType
  onlyLeafNodeVar?: boolean
  filterVar?: (payload: Var, valueSelector: ValueSelector) => boolean
  availableNodes?: Node[]
  availableVars?: NodeOutPutVar[]
  isAddBtnTrigger?: boolean
  schema?: Partial<CredentialFormSchema>
  valueTypePlaceHolder?: string
  isInTable?: boolean
  onRemove?: () => void
  typePlaceHolder?: string
  isSupportFileVar?: boolean
  placeholder?: string
  minWidth?: number
  popupFor?: 'assigned' | 'toAssigned'
  zIndex?: number
}

const props = defineProps<Props>();
  const vueFlow = useVueFlow()
  const {
    getNodes,
  } = vueFlow
  const isChatMode = useIsChatMode()

  const { getCurrentVariableType } = useWorkflowVariables()
  const { availableVars, availableNodesWithParent: availableNodes } = useAvailableVarList(props.nodeId, {
    onlyLeafNodeVar:props.onlyLeafNodeVar,
    passedInAvailableNodes:props.availableNodes,
    filterVar:props.filterVar,
  })
  const startNode = availableNodes.find((node: any) => {
    return node.data.type === BlockEnum.Start
  })

  const node = getNodes.value.find(n => n.id === props.nodeId)
  const isInIteration = !!node?.data.isInIteration
  const iterationNode = isInIteration ? getNodes.value.find(n => n.id === node.parentNode) : null

  const isInLoop = !!node?.data.isInLoop
  const loopNode = isInLoop ? getNodes.value.find(n => n.id === node.parentNode) : null
  const triggerWidth = ref(TRIGGER_DEFAULT_WIDTH);
  const varKindType=  ref<VarKindType>(props.defaultVarKindType)
  const open = ref(false);
  // useEffect(() => {
  //   if (triggerRef.current)
  //     setTriggerWidth(triggerRef.current.clientWidth)
  // })

  const isConstant =  computed(()=> props.isSupportConstantValue && varKindType === VarKindType.constant) 

  const outputVars = computed(() => (props.availableNodes || availableVars) && [props.availableNodes, availableVars])

  watch(open,() => {
    if(props.onOpen)
       props.onOpen()
  })
  const hasValue = !isConstant && props.value.length > 0

  const isIterationVar = computed(() => {
    if (!isInIteration)
      return false
    if (props.value[0] === node?.parentNode && ['item', 'index'].includes(props.value[1]))
      return true
    return false
  })

  const isLoopVar = computed(() => {
    if (!isInLoop)
      return false
    if (props.value[0] === node?.parentNode && ['item', 'index'].includes(props.value[1]))
      return true
    return false
  })

  const outputVarNodeId = hasValue ? props.value[0] : ''
  const outputVarNode = computed(() => {
    if (!hasValue || isConstant)
      return null

    if (isIterationVar)
      return iterationNode?.data

    if (isLoopVar)
      return loopNode?.data

    if (isSystemVar(props.value as ValueSelector))
      return startNode?.data

    return getNodeInfoById(availableNodes, outputVarNodeId)?.data
  })

  const varName = computed(() => {
    if (hasValue) {
      const isSystem = isSystemVar(props.value as ValueSelector)
      let varName = ''
      if (Array.isArray(props.value))
        varName = props.value.length >= 3 ? (props.value as ValueSelector).slice(-2).join('.') : props.value[props.value.length - 1]

      return `${isSystem ? 'sys.' : ''}${varName}`
    }
    return ''
  })

  const varKindTypes = [
    {
      label: 'Variable',
      value: VarKindType.variable,
    },
    {
      label: 'Constant',
      value: VarKindType.constant,
    },
  ]

  const handleVarKindTypeChange = (value: VarKindType) => {
    varKindType.value = value;
    if (value === VarKindType.constant)
      props.onChange('', value)
    else
    props.onChange([], value)
  }
  const isFocus = ref(false);
  const controlFocus = ref<number>();
  const inputRef = ref<HTMLInputElement>();

  watch(controlFocus,() => {
    if (controlFocus.value && inputRef.value) {
      inputRef.value.focus()
      isFocus.value = true
    }
  })

  const handleVarReferenceChange = (value: ValueSelector, varInfo: Var) => {
    // sys var not passed to backend
      if (props.value[1] && props.value[1].startsWith('sys.')) {
        props.value.shift()
        const paths = props.value[0].split('.')
        paths.forEach((p, i) => {
          props.value[i] = p
        })
      }
    props.onChange(props.value, varKindType, varInfo)
    open.value = false;
  }

  const handleClearVar = () => {
    if (varKindType === VarKindType.constant)
      props.onChange('', varKindType)
    else
      props.onChange([], varKindType)
  }

  const type = getCurrentVariableType({
    parentNode: isInIteration ? iterationNode : loopNode,
    valueSelector: props.value as ValueSelector,
    availableNodes,
    isChatMode,
    isConstant: !!isConstant,
  })

  const isEnv = computed(()=> isENV(props.value as ValueSelector));
  const isChatVar = computed(()=> isConversationVar(props.value as ValueSelector));
  const isValidVar = computed(()=> Boolean(outputVarNode.value) || isEnv.value || isChatVar.value);
  const isException = computed(()=> isExceptionVariable(varName.value, outputVarNode.value?.type));

  // 8(left/right-padding) + 14(icon) + 4 + 14 + 2 = 42 + 17 buff
  const PRIORITY_WIDTH = 15
  const availableWidth = computed(()=> triggerWidth.value - 56);
  const totalTextLength = computed(()=> ((outputVarNode.value?.title || '') + (varName || '') + (type || '')).length);
  const maxNodeNameWidth = computed(()=> PRIORITY_WIDTH + Math.floor((outputVarNode.value?.title?.length || 0) / totalTextLength.value * availableWidth.value));
  const maxVarNameWidth = computed(()=> -PRIORITY_WIDTH + Math.floor((varName.value?.length || 0) / totalTextLength.value * availableWidth.value));
  const maxTypeWidth = computed(()=> Math.floor((type?.length || 0) / totalTextLength.value * availableWidth.value));

  // const WrapElem = props.isSupportConstantValue ? 'div' : PortalToFollowElemTrigger
  // const VarPickerWrap = !isSupportConstantValue ? 'div' : PortalToFollowElemTrigger
</script>